package net.pws.common.jackson;

import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

//import com.fasterxml.jackson.module.hibernate.HibernateModule;

@SuppressWarnings("rawtypes")
public class JsonUtils {
    
    private static final transient Log logger = LogFactory.getLog(JsonUtils.class);
    
    public static final SimpleDateFormat shortFormatter = new SimpleDateFormat("yyyy-MM-dd");
    
    public static final SimpleDateFormat longFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    public static ObjectMapper objectMapper = new ObjectMapper();
    
    static {
        //objectMapper.registerModule(new HibernateModule());
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS,
                               false);
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,
                               false);
        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,
                               false);
        objectMapper.getSerializationConfig().withDateFormat(longFormatter);
        objectMapper.getDeserializationConfig().withDateFormat(longFormatter);
        objectMapper.setDateFormat(longFormatter);
    }
    
    public static Object deepClone(Object obj) {
        return parseJson(toJson(obj), obj.getClass());
    }
    
    public static <T> T parseJson(String content, Class<T> clazz) {
        try {
            return objectMapper.readValue(content, clazz);
        }
        catch (Exception e) {
        	logger.error(e, e);
        }
        return null;
    }
    
	public static List parseList(String content) {
        try {
            return objectMapper.readValue(content, List.class);
        }
        catch (Exception e) {
        	logger.error(e, e);
        }
        return null;
    }
    
    public static Map parseMap(String content) {
        try {
            return objectMapper.readValue(content, Map.class);
        }
        catch (Exception e) {
        	logger.error(e, e);
        }
        return null;
    }
    
    public static String toJson(Object obj) {
        try {
            StringWriter sw = new StringWriter();
            JsonGenerator jsonGenerator = objectMapper.getJsonFactory()
                                                      .createJsonGenerator(sw);
            objectMapper.writeValue(jsonGenerator, obj);
            jsonGenerator.flush();
            return sw.getBuffer().toString();
        }
        catch (IOException e) {
        	logger.error(e, e);
        }
        return null;
    }
    
    public static Map<String, Object> succeedMap(Object obj) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.TRUE);
        if (null != obj) {
            result.put("data", obj);
        }
        return result;
    }
    
    public static Map<String, Object> failedMap(String message) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        return result;
    }
    
    public static Map<String, Object> failedMap(String message,
                                                String code,
                                                String field) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        Map<String, Object> errorDetail = new HashMap<String, Object>();
        errorDetail.put("code", code);
        errorDetail.put("field", field);
        result.put("error", errorDetail);
        return result;
    }
    
    public static String succeedJson(Object obj) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.TRUE);
        if (null != obj) {
            result.put("data", obj);
        }
        return toJson(result);
    }
    
    public static String failedJson(String message) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("succeed", Boolean.FALSE);
        result.put("message", message);
        return toJson(result);
    }
    
}
